%{
#include <stdio.h>
#include <string.h>

// stuff from lex that yacc needs to know about:
extern int yylex();
extern int yyparse();
extern FILE *yyin;

void yyerror(const char *str){
	fprintf(stderr,"Error: %s\n",str);
}

int yywrap(){
	return 1;
}

main(int argc, char *argv[]) {
	if (argc != 2) {
		printf("Error. Usage: %s filename", argv[0]);
    }
    
	// open a file handle to a particular file:
	FILE *myfile = fopen(argv[1], "r");
	// make sure it is valid:
	if (!myfile) {
		printf("Cannot open file: %s",argv[1]);
		return -1;
	}
	// set lex to read from it instead of defaulting to STDIN:
	yyin = myfile;
	// parse through the input until there is no more:
	do {
		yyparse();
	} while (!feof(yyin));
}

%}

%union {
	int ival;
	float fval;
	char *sval;
}
%token TK_AND
%token TK_OR
%token TK_IF
%token TK_THEN
%token TK_ELSE
%token TK_ENDIF
%token TK_DO
%token TK_WHILE
%token TK_LOOP
%token TK_DOCASE
%token TK_ENDCASE
%token TK_CASE
%token TK_OTHER
%token TK_DECLARE
%token TK_ENDDECLARE
%token TK_OUT
%token TK_ROUNDEVEN
%token TK_TD_INT
%token TK_TD_FLOAT
%token TK_TD_STRING
%token TK_ID
%token TK_INT
%token TK_FLOAT
%token TK_STRING
%token TK_COMMENT
%token TK_QUOTE
%token TK_MINUS
%token TK_PLUS
%token TK_MULTIPLY
%token TK_DIVIDE
%token TK_ASSIGN
%token TK_NOT
%token TK_GREATERTHAN
%token TK_LESSTHAN
%token TK_OBRACKET
%token TK_EBRACKET
%token TK_OSQBRACKET
%token TK_ESQBRACKET
%token TK_COLLON
%token TK_COMMA
%token TK_ENDL
%token TK_WHITESPACE
%%

PROGRAMA:
	PROGRAMA SENTENCIA
	| SENTENCIA
	;

SENTENCIA:
	ASIGNACION
	| ITER
	| DECISION
	| DECLARACION
	| PRINT
	| COMMENT
	| TK_ENDL
	;

ASIGNACION:
	TK_ID TK_ASSIGN EXP {printf("ASIGNACION EXP\n");}
	;

ITER:
	TK_WHILE CONDICION TK_DO PROGRAMA TK_LOOP {printf("WHILE\n");}
	;

DECISION:
	TK_IF TK_OBRACKET CONDICION TK_EBRACKET TK_THEN PROGRAMA TK_ENDIF {printf("IF THEN\n");}
	| TK_IF TK_OBRACKET CONDICION TK_EBRACKET TK_THEN PROGRAMA TK_ELSE PROGRAMA TK_ENDIF {printf("IF THEN ELSE\n");}
	| TK_DOCASE TK_ENDL LISTACASE TK_ENDCASE {printf("SELECT CASE\n");}
	| TK_DOCASE TK_ENDL LISTACASE TK_OTHER PROGRAMA TK_ENDCASE {printf("SELECT CASE OTHER\n");}
	;

LISTACASE:
	LISTACASE CASE
	| CASE
	;

CASE:
	TK_CASE CONDICION PROGRAMA {printf("CASE\n");}
	;

CONDICION:
	COMP TK_AND COMP {printf("COMP AND COMP\n");}
	| COMP TK_OR COMP {printf("COMP OR COMP\n");}
	| COMP {printf("COMP\n");}
	| TK_NOT COMP {printf("NOT COMP\n");}
	;

COMP:
	EXP COMPARADOR EXP {printf("COMPARACION\n");}
	;

EXP:
	EXP TK_PLUS TERMINO {printf("EXP + TERMINO\n");}
	| EXP TK_MINUS TERMINO {printf("EXP - TERMINO\n");}
	| TERMINO {printf("TERMINO\n");}
	;

TERMINO:
	TERMINO TK_MULTIPLY FACTOR {printf("TERMINO * FACTOR\n");}
	| TERMINO TK_DIVIDE FACTOR {printf("TERMINO / FACTOR\n");}
	| FACTOR {printf("FACTOR\n");}
	;

FACTOR:
	TK_ID {printf("FACTOR ID\n");}
	| CTE {printf("FACTOR CTE\n");}
	| TK_OBRACKET EXP TK_EBRACKET {printf("FACTOR (EXP)\n");}
	| REDONDEOPAR {printf("REDONDEOPAR\n");}
	;

PRINT:
	TK_OUT TK_OBRACKET TK_STRING TK_EBRACKET {printf("OUT STRING\n");}
	| TK_OUT TK_OBRACKET TK_ID TK_EBRACKET {printf("OUT ID\n");}
	;

DECLARACION:
	TK_DECLARE TIPODATO TK_COLLON TK_OSQBRACKET LISTA_IDS TK_ESQBRACKET TK_ENDDECLARE {printf("DECLARE\n");}
	;

LISTA_IDS:
	LISTA_IDS TK_COMMA TK_ID
	| TK_ID
	;

TIPODATO:
	TK_TD_INT
	| TK_TD_FLOAT
	| TK_TD_STRING;

CTE:
	TK_INT {printf("CTE INT\n");}
	| TK_FLOAT {printf("CTE FLOAT\n");}
	| TK_STRING {printf("CTE STRING\n");}
	;

REDONDEOPAR:
	TK_ROUNDEVEN TK_OBRACKET EXP TK_EBRACKET {printf("ROUNDEVEN\n");}
	;

COMPARADOR:
	TK_LESSTHAN {printf("<\n");}
	| TK_GREATERTHAN {printf(">\n");}
	| TK_ASSIGN TK_ASSIGN {printf("==\n");}
	| TK_NOT TK_ASSIGN {printf("!=\n");}
	;
	
COMMENT:
	TK_COMMENT TK_ENDL {printf("COMENTARIO\n");}
	;